import 'package:flutter/material.dart';
import 'dart:math' as math;

class BGDashedRectWidget extends StatelessWidget {
  final Color color;

  final double strokeWidth;

  final double gap;

  final Widget child;

  final Map paintRect;

  BGDashedRectWidget({
    required this.child,
    this.color = Colors.black,
    this.strokeWidth = 1.0,
    /*边框的宽度*/

    this.gap = 2,
    /*虚边框的间隙*/

    this.paintRect = const {"left": true, "top": true, "right": true, "bottom": true},
    /*左右上下，代表是否要描绘边框*/
  });

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: <Widget>[
        Positioned.fill(
            child: CustomPaint(
          painter: DashRectPainter(color: this.color, strokeWidth: this.strokeWidth, gap: this.gap, paintRect: this.paintRect),
        )),
        Padding(
          padding: const EdgeInsets.all(2),
          child: child,
        ),
      ],
    );
  }
}

class DashRectPainter extends CustomPainter {
  double strokeWidth;

  Color color;

  double gap;

  Map paintRect;

  DashRectPainter(
      {this.strokeWidth = 5.0,
      this.color = Colors.red,
      this.gap = 5.0,
      this.paintRect = const {"left": true, "top": true, "right": true, "bottom": true}});

  @override
  void paint(Canvas canvas, Size size) {
    Paint dashedPaint = Paint()
      ..color = color
      ..strokeWidth = strokeWidth
      ..style = PaintingStyle.stroke;

    double x = size.width;

    double y = size.height;

    if (this.paintRect["top"]) {
      Path _topPath = getDashedPath(
        a: math.Point(0, 0),
        b: math.Point(x, 0),
        gap: gap,
      );

      canvas.drawPath(_topPath, dashedPaint);
    }

    if (this.paintRect['right']) {
      Path _rightPath = getDashedPath(
        a: math.Point(x, 0),
        b: math.Point(x, y),
        gap: gap,
      );

      canvas.drawPath(_rightPath, dashedPaint);
    }

    if (this.paintRect['bottom']) {
      Path _bottomPath = getDashedPath(
        a: math.Point(0, y),
        b: math.Point(x, y),
        gap: gap,
      );

      canvas.drawPath(_bottomPath, dashedPaint);
    }

    if (this.paintRect['left']) {
      Path _leftPath = getDashedPath(
        a: math.Point(0, 0),
        b: math.Point(0.001, y),
        gap: gap,
      );

      canvas.drawPath(_leftPath, dashedPaint);
    }
  }

  Path getDashedPath({
    required math.Point<double> a,
    required math.Point<double> b,
    required gap,
  }) {
    Size size = Size(b.x - a.x, b.y - a.y);

    Path path = Path();

    path.moveTo(a.x, a.y);

    bool shouldDraw = true;

    math.Point currentPoint = math.Point(a.x, a.y);

    num radians = math.atan(size.height / size.width);

    num dx = math.cos(radians) * gap < 0 ? math.cos(radians) * gap * -1 : math.cos(radians) * gap;

    num dy = math.sin(radians) * gap < 0 ? math.sin(radians) * gap * -1 : math.sin(radians) * gap;

    while (currentPoint.x <= b.x && currentPoint.y <= b.y) {
      shouldDraw
          ? path.lineTo(currentPoint.x.toDouble(), currentPoint.y.toDouble())
          : path.moveTo(currentPoint.x.toDouble(), currentPoint.y.toDouble());

      shouldDraw = !shouldDraw;

      currentPoint = math.Point(
        currentPoint.x + dx,
        currentPoint.y + dy,
      );
    }

    return path;
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    return true;
  }
}
